package {
	import flash.display.Bitmap;
	import flash.display.StageQuality;
	import flash.events.Event;
	import flash.events.KeyboardEvent;
	import flash.ui.Keyboard;
	import flash.utils.ByteArray;
	import flash.utils.Dictionary;
	import flash.utils.getTimer;
	
	import jiglib.geometry.JPlane;
	import jiglib.math.JNumber3D;
	import jiglib.physics.PhysicsSystem;
	import jiglib.plugin.papervision3d.Pv3dMesh;
	import jiglib.vehicles.JCar;
	
	import org.papervision3d.cameras.SpringCamera3D;
	import org.papervision3d.core.clipping.FrustumClipping;
	import org.papervision3d.core.math.Number3D;
	import org.papervision3d.materials.BitmapMaterial;
	import org.papervision3d.materials.utils.MaterialsList;
	import org.papervision3d.objects.DisplayObject3D;
	import org.papervision3d.objects.parsers.DAE;
	import org.papervision3d.objects.primitives.Plane;
	import org.papervision3d.view.BasicView;
	import org.papervision3d.view.layer.ViewportLayer;
	import org.papervision3d.view.layer.util.ViewportLayerSortMode;
	import org.papervision3d.view.stats.StatsView;

	[SWF(width="1024", height="768", backgroundColor="#ffffff", frameRate="30")]
	
	public class JigLibCar extends BasicView
	{
		[Embed(source="assets/Focus.dae", mimeType = "application/octet-stream")]
		private var carAsset:Class;
		
		[Embed(source="/assets/wheel.jpg")]
		private var wheelBitmapAsset:Class;
		
		[Embed(source="/assets/body.jpg")]
		private var bodyBitmapAsset:Class;

		[Embed(source="/assets/grassTexture.jpg")]
		private var grassTextureBitmapAsset:Class;
		
		private var ground:Plane
		private var car:DAE;
		private var steerFR :DisplayObject3D;
		private var steerFL :DisplayObject3D;
		private var wheelFR :DisplayObject3D;
		private var wheelFL :DisplayObject3D;
		private var wheelRR :DisplayObject3D;
		private var wheelRL :DisplayObject3D;
		private var springCamera:SpringCamera3D;
		private var carMaterials:MaterialsList;
		private var skins: Dictionary = new Dictionary(true);
		
		private var jCar:JCar;
		
		private var deltaTime:Number = 0;
        private var currentTime:uint;
		private var newTime:uint;
		private var physicsSpeed: Number = 5;
		
		public function JigLibCar()
		{
			super();
			setupScene();
			setupPhysics();
			stage.quality = StageQuality.MEDIUM;
			
			stage.addEventListener( KeyboardEvent.KEY_DOWN, keyDownHandler );
			stage.addEventListener( KeyboardEvent.KEY_UP, keyUpHandler );
			addEventListener(Event.ENTER_FRAME, onEnterFrame);
		}
		
		private function setupScene():void
		{
			renderer.clipping = new FrustumClipping(FrustumClipping.BOTTOM);
			
			springCamera = new SpringCamera3D();
			springCamera.mass = 10;
			springCamera.damping = 10;
			springCamera.stiffness = 1;
			springCamera.lookOffset = new Number3D(0,10,10);
			
			springCamera.positionOffset = new Number3D(0,25,-25);
			springCamera.near = -10000;
			
			var wheelBmp:Bitmap = new wheelBitmapAsset() as Bitmap;
			var bodyBmp:Bitmap  = new bodyBitmapAsset() as Bitmap;
			var grassBmp:Bitmap = new grassTextureBitmapAsset() as Bitmap;
			
			var wheelMat:BitmapMaterial = new BitmapMaterial(wheelBmp.bitmapData);
			wheelMat.smooth = true;
			var bodyMat:BitmapMaterial  = new BitmapMaterial(bodyBmp.bitmapData);
			bodyMat.smooth = true;
			var grassMat:BitmapMaterial = new BitmapMaterial(grassBmp.bitmapData);
			grassMat.precise = true;
			grassMat.tiled = true;
			grassMat.maxU = 2;
			grassMat.maxV = 2;
			grassMat.smooth = true;
			
			carMaterials = new MaterialsList();
			carMaterials.addMaterial(bodyMat, "materialBody");
			carMaterials.addMaterial(wheelMat, "materialWheel");
			 
			var ba:ByteArray = new carAsset() as ByteArray;
			car = new DAE(true);
			car.load(ba, carMaterials);
			car.scale = 2;
			car.useClipping = false;
			
			steerFR = car.getChildByName( "Steer_FR", true );
			steerFL = car.getChildByName( "Steer_FL", true );
			wheelFR = steerFR.getChildByName( "Wheel_FR", true );
			wheelFL = steerFL.getChildByName( "Wheel_FL", true );
			wheelRR = car.getChildByName( "Wheel_RR", true );
			wheelRL = car.getChildByName( "Wheel_RL", true );			
			
			springCamera.target = car;
			
			scene.addChild(car);
			
			ground = new Plane(grassMat, 1000, 1000, 2, 2);
			//ground.y = -10;
			scene.addChild(ground);
			
			viewport.containerSprite.sortMode = ViewportLayerSortMode.INDEX_SORT;
			
			var carVpLayer:ViewportLayer = new ViewportLayer(viewport, car);
			carVpLayer.addDisplayObject3D(car, true);
			carVpLayer.layerIndex = 1;
			
			viewport.containerSprite.addLayer(carVpLayer);
			camera.target = car;
			
			
			var stats:StatsView = new StatsView(renderer);
			addChild(stats);
		}
		
		private function setupPhysics():void
		{
			currentTime = getTimer(); 
			
			var jPlane:JPlane = new JPlane(new Pv3dMesh(ground));
			jPlane.moveTo(new JNumber3D(0, 260, 0));
			jPlane.rotationX = 90;
			//jPlane.rotationY = Math.PI/2;

			PhysicsSystem.getInstance().addBody(jPlane);
			
			jCar = new JCar(new Pv3dMesh(car));
			jCar.setCar(45, 4, 750);
			jCar.chassis.moveTo(new JNumber3D( 0, 310, -100));
			jCar.chassis.rotationY = Math.PI/2;
			jCar.chassis.mass=8;
			//jCar.chassis.material.DynamicFriction = 0.5;
			jCar.chassis.sideLengths = new JNumber3D(50, 20, 70);
			PhysicsSystem.getInstance().addBody(jCar.chassis);

			var steerFR :DisplayObject3D = car.getChildByName( "Steer_FR", true );
			var steerFL :DisplayObject3D = car.getChildByName( "Steer_FL", true );
			//var body :DisplayObject3D = car.getChildByName( "Body", true );
			//var b:BoundingSphere = body.geometry.boundingSphere;

			jCar.setupWheel("wheel_fl", new JNumber3D( -30, -5, 32), 	1.2, 1.5, 3, 8, 0.4, 0.5, 2);
			jCar.setupWheel("wheel_fr", new JNumber3D(30, -5, 32), 		1.2, 1.5, 3, 8, 0.4, 0.5, 2);
			jCar.setupWheel("wheel_bl", new JNumber3D( -30, -5, -32), 	1.2, 1.5, 3, 8, 0.4, 0.5, 2);
			jCar.setupWheel("wheel_br", new JNumber3D(30, -5, -32), 	1.2, 1.5, 3, 8, 0.4, 0.5, 2);
		}
		
		private function onEnterFrame(e:Event):void
		{
			PhysicsSystem.getInstance().integrate(0.1);
			updateCar();
			singleRender();
		}
		
		private function updateCar():void
		{
			steerFL.rotationY = jCar.wheels["wheel_fl"].getSteerAngle()*-1;
			steerFR.rotationY = jCar.wheels["wheel_fr"].getSteerAngle()*-1;
			
			wheelFR.roll(jCar.wheels["wheel_fr"].getRollAngle());
			wheelFL.roll(-jCar.wheels["wheel_fl"].getRollAngle());
			wheelRR.roll(jCar.wheels["wheel_br"].getRollAngle());
			wheelRL.roll(-jCar.wheels["wheel_bl"].getRollAngle());
		}
		
		private function keyDownHandler(event :KeyboardEvent):void
		{
			switch(event.keyCode)
			{
				case Keyboard.UP:
					jCar.setAccelerate(2);
					break;
				case Keyboard.DOWN:
					jCar.setAccelerate(-1);
					break;
				case Keyboard.LEFT:
					jCar.setSteer(["wheel_fl", "wheel_fr"], -1.5);
					break;
				case Keyboard.RIGHT:
					jCar.setSteer(["wheel_fl", "wheel_fr"], 1.5);
					break;
				case Keyboard.SPACE:
					jCar.setHBrake(1);
					break;
			}
		}


		private function keyUpHandler(event:KeyboardEvent):void
		{
			switch(event.keyCode)
			{
				case Keyboard.UP:
					jCar.setAccelerate(0);
					break;
				case Keyboard.DOWN:
					jCar.setAccelerate(0);
					break;
				case Keyboard.LEFT:
					jCar.setSteer(["wheel_fl", "wheel_fr"], 0);
					break;
				case Keyboard.RIGHT:
					jCar.setSteer(["wheel_fl", "wheel_fr"], 0);
					break;
				case Keyboard.SPACE:
				   jCar.setHBrake(0);
			}
		}		
		
		override protected function onRenderTick(event:Event=null):void
		{
			renderer.renderScene(scene, springCamera, viewport);
		}
	}
}
